package com.huajx.core.server;

import java.io.IOException;
import java.net.InetSocketAddress;

import com.huajx.core.annotation.RouteBundle;
import com.huajx.core.handler.RouteHandler;
import com.huajx.core.server.annonation.MinaServer;
import com.huajx.core.server.config.HbootServerConfig;
import com.huajx.util.CharsetUtil;
import com.huajx.util.StrUtil;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.huajx.core.codec.HttpRequestDecoder;
import com.huajx.core.codec.HttpResponseEncoder;
import com.huajx.core.codec.HttpServerProtocolCodecFactory;
import com.huajx.core.handler.HttpHandler;
import com.huajx.core.handler.ServerHandler;

@MinaServer(name = "http", port = 8888)
public class HttpServer implements HbootServer {
    private final static Logger logger = LoggerFactory.getLogger(HttpServer.class);
    /**
     * Default HTTP port
     */
    public static final int DEFAULT_PORT = 8888;

    private String serverName;
    private int port;

    private String describe;


    private NioSocketAcceptor acceptor;
    private boolean isRunning;

    private String encoding;
    private HttpHandler httpHandler;

    public String getEncoding() {
        return encoding;
    }

    public void setEncoding(String encoding) {
        this.encoding = encoding;
        HttpRequestDecoder.defaultEncoding = encoding;
        HttpResponseEncoder.defaultEncoding = encoding;
    }

    public HttpHandler getHttpHandler() {
        return httpHandler;
    }

    public void setHttpHandler(HttpHandler httpHandler) {
        this.httpHandler = httpHandler;
    }

    /**
     * 启动HTTP服务端箭筒HTTP请求
     *
     * @param port 要监听的端口号
     * @throws IOException
     */
    public void start(int port) throws IOException {
        synchronized (this) {
            if (isRunning) {
                logger.warn("Web服务器已经启动！");
                return;
            }

            if (port < 80) {
                port = DEFAULT_PORT;
            }

            acceptor = new NioSocketAcceptor();
            acceptor.getFilterChain().addLast("protocolFilter",
                    new ProtocolCodecFilter(new HttpServerProtocolCodecFactory()));
            acceptor.getFilterChain().addLast("logger", new LoggingFilter());
            ServerHandler handler = new ServerHandler();
            handler.setHandler(httpHandler);
            acceptor.setHandler(handler);
            acceptor.setReuseAddress(true);
            acceptor.bind(new InetSocketAddress(port));
            isRunning = true;

            /**
             * 扫描所有Route类
             */
            RouteBundle.me().scan();

            logger.info("{} 服务启动完毕，监听端口:{}, {}" , serverName, port, describe);
        }
    }

    /**
     * 使用默认端口8080
     */
    @Override
    public void start() {
        try {
            start(port);
        } catch (IOException e) {
            String msg = e.getMessage();
            if(msg.contains("Address already in use")){
                stop();
            }
            logger.error(e.getMessage());
//            e.printStackTrace();
        }
    }

    /**
     * 停止监听HTTP服务
     */
    @Override
    public void stop() {
//		synchronized (this) {
        if (!isRunning) {
            if (acceptor.isActive()) {
                acceptor.unbind();
                acceptor.dispose();
            }
            logger.warn("Web服务器已经停止！");
            return;
        }
        isRunning = false;
        try {
            acceptor.unbind();
            acceptor.dispose();
            logger.info("Web服务器停止成功！");
        } catch (Exception e) {
            e.printStackTrace();
        }
//		}
    }

    @Override
    public void config(HbootServerConfig config) {
        this.port = config.getPort() <= 80 ? DEFAULT_PORT : config.getPort();
        this.serverName = config.getName();
        this.describe = config.getDescribe();
        setEncoding(StrUtil.isBlank(config.getEncoding()) ? CharsetUtil.UTF_8 : config.getEncoding());
        setHttpHandler(new RouteHandler());
    }

    //	public static void main(String[] args) {
//		int port = DEFAULT_PORT;
//
//		for (int i = 0; i < args.length; i++) {
//			if (args[i].equals("-port")) {
//				port = Integer.parseInt(args[i + 1]);
//			}
//		}
//
//		try {
//			// Create an acceptor
//			NioSocketAcceptor acceptor = new NioSocketAcceptor();
//
//			// Create a service configuration
//			acceptor.getFilterChain().addLast("protocolFilter",
//					new ProtocolCodecFilter(new HttpServerProtocolCodecFactory()));
//			acceptor.getFilterChain().addLast("logger", new LoggingFilter());
//			acceptor.setHandler(new ServerHandler());
//			acceptor.bind(new InetSocketAddress(port));
//
//			System.out.println("MinaServer now listening on port " + port);
//		} catch (Exception ex) {
//			ex.printStackTrace();
//		}
//	}

    @Override
    public boolean isRunning() {
        return isRunning;
    }
}
